﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace XDCCManager.Network
{
	public class ConnectionErrorEventArgs : EventArgs
	{
		public ConnectionErrorEventArgs(string message)
		{
			Message = message;
		}

		public string Message { get; private set; }
	}

	public class ConnectionStateEventArgs : EventArgs
	{
		public enum ConnectionState
		{
			Idle,
			AddressResolving,
			AddressResolutionFail,
			AddressResolved,
			ServerConnecting,
			ServerConnectFail,
			SslNegotiating,
			SslNegotiationFailed,
			ServerConnected,
			WaitingMotd,
			RequestingChat,
			Identifying,
			IOError,
			Disconnected,
			Ready
		}

		/// <summary>
		/// Builds a ConnectionStateEventArgs for ConnectionState.Idle, ConnectionState.WaitingMotd, ConnectionState.RequestingChat, ConnectionState.Identifying, ConnectionState.Disconnected and ConnectionState.Ready.
		/// </summary>
		/// <param name="state">The connection state. Valid values are ConnectionState.Idle, ConnectionState.RequestingChat, ConnectionState.Identifying, ConnectionState.Disconnected and ConnectionState.Ready.</param>
		public ConnectionStateEventArgs(ConnectionState state)
		{
			State = state;
			Parameters = new object[0];
		}

		/// <summary>
		/// Builds a ConnectionStateEventArgs for ConnectionState.AddressResolving and ConnectionState.AddressResolutionFail.
		/// </summary>
		/// <param name="state">The connection state. Valid values are ConnectionState.AddressResolving and ConnectionState.AddressResolutionFail.</param>
		/// <param name="serverAddress">The server address.</param>
		public ConnectionStateEventArgs(ConnectionState state, Model.Servers.ServerAddress serverAddress)
		{
			State = state;
			Parameters = new object[1] { serverAddress.Hostname };
		}

		/// <summary>
		/// Builds a ConnectionStateEventArgs for ConnectionState.AddressResolved.
		/// </summary>
		/// <param name="state">The connection state. Valid value is ConnectionState.AddressResolved</param>
		/// <param name="serverAddress">The server address</param>
		/// <param name="addresses">The list of resolved IP addresses.</param>
		public ConnectionStateEventArgs(ConnectionState state, Model.Servers.ServerAddress serverAddress, System.Net.IPAddress[] addresses)
		{
			State = state;
			string[] stringAddresses = new string[addresses.Length];
			for (int i = 0; i < stringAddresses.Length; i++)
				stringAddresses[i] = addresses[i].ToString();
			Parameters = new object[2] { serverAddress.Hostname, string.Join(", ", stringAddresses) };
		}

		/// <summary>
		/// Builds a ConnectionStateEventArgs for ConnectionState.ServerConnecting, ConnectionState.ServerConnectFail, ConnectionState.SslNegotiating, ConnectionState.SslNegotiationFail and ConnectionState.ServerConnected.
		/// </summary>
		/// <param name="state">The connection state. Valid values are ConnectionState.ServerConnecting, ConnectionState.ServerConnectFail, ConnectionState.SslNegotiating, ConnectionState.SslNegotiationFail and ConnectionState.ServerConnected.</param>
		/// <param name="serverAddress">The server address.</param>
		/// <param name="address">The currently used IP address.</param>
		public ConnectionStateEventArgs(ConnectionState state, Model.Servers.ServerAddress serverAddress, System.Net.IPAddress address)
		{
			State = state;
			Parameters = new object[2] { serverAddress.Hostname, new System.Net.IPEndPoint(address, serverAddress.Port) };
		}

		/// <summary>
		/// Builds a ConnectionStateEventArgs for ConnectionState.IOError.
		/// </summary>
		/// <param name="state">The connection state. Valid value is ConnectionState.IOError.</param>
		/// <param name="exception">The raised exception.</param>
		public ConnectionStateEventArgs(ConnectionState state, Exception exception)
		{
			State = state;
			Parameters = new object[1] { exception.Message };
		}

		public ConnectionState State { get; private set; }
		public object[] Parameters { get; private set; }

		public string Message
		{
			get
			{
				string message = string.Empty;
				switch (State)
				{
					case ConnectionState.Idle:
						message = "Idle.";
						break;
					case ConnectionState.AddressResolving:
						message = "Resolving address {0}.";
						break;
					case ConnectionState.AddressResolutionFail:
						message = "Failed to resolve address {0}.";
						break;
					case ConnectionState.AddressResolved:
						message = "Address {0} resolved to {1}.";
						break;
					case ConnectionState.ServerConnecting:
						message = "Connecting to {0} ({1}).";
						break;
					case ConnectionState.ServerConnectFail:
						message = "Unable to connect to {0} ({1}).";
						break;
					case ConnectionState.ServerConnected:
						message = "Connected to {0} ({1}).";
						break;
					case ConnectionState.WaitingMotd:
						message = "Waiting message of the day.";
						break;
					case ConnectionState.RequestingChat:
						message = "Requesting chat with the XDCC server user.";
						break;
					case ConnectionState.Identifying:
						message = "Identifying ourself in the chat session.";
						break;
					case ConnectionState.IOError:
						message = "An exception occured while reading or writing to server.\nMessage: {0}";
						break;
					case ConnectionState.Disconnected:
						message = "The connection to the server has been terminated.";
						break;
					case ConnectionState.Ready:
						message = "The connection is ready for commands.";
						break;
				}
				return string.Format(message, Parameters);
			}
		}
	}

	public class MessageEventArgs : EventArgs
	{
		public MessageEventArgs(IRCEngine.Message message)
		{
			Message = message;
		}

		public IRCEngine.Message Message { get; private set; }
	}

	public class LineEventArgs : EventArgs
	{
		public LineEventArgs(string line)
		{
			Line = line;
		}

		public string Line { get; private set; }
	}
}
